#include<iostream>
#include<sstream>
#include<bitset>

#include "../common/CargadorMasivo.h"
#include "../common/QueryEjecutor.h"
#include <getopt.h>
#include "sys/stat.h"

bool controlParametros(int argc, char** argv);

char *argFalla = NULL, *argFormacion = NULL ,
		*argAccidente = NULL, *argFechaMayor = NULL, *argFechaMenor= NULL,
		*argCargaInicial =NULL;

std::string rangoHorarioyFechaMenor, rangoHorarioyFechaMayor;

bool filtra_fecha_menor_a=false,
		filtra_fecha_mayor_a = false,
		filtra_falla = false,
		filtra_accidentes = false,
		filtra_lineas = false,
		filtra_formaciones = false,
		carga_inicial = false,
		alta=false;

bool fileExists(const char* filename){
	struct stat buffer;

	if(stat(filename, &buffer) != -1)
		return true;

	return false;
}

void consultaAccidentesFormacion(std::string& formacion, std::string& rango_menor, std::string& rango_mayor){
	unsigned int anio;
	unsigned char mes, dia;
	std::string rangoHoras;
	Point<DIMENSION_CLAVES> min, max;
	std::string dirInput = getenv("OUTPUT");
	std::string archSalida = dirInput.append("/").append(PATH_QUERY_ACCIDENTES_FORMACION);
	u_int32_t idFormacion = (u_int32_t) (atoi(formacion.c_str())) ;
	Mapeador* mapeador = Mapeador::getInstance();


	if (rango_mayor.size() != 0){
		mapeador->mapearFechaLeida(rango_mayor, &anio, &mes, &dia, &rangoHoras);
		u_int32_t idRango = mapeador->convertirRango(anio, mes, dia, rangoHoras);
		min = {ID_CLAVE_VACIA,idRango,ID_CLAVE_VACIA, ID_CLAVE_INICIAL, idFormacion};
	}
	else{
		min = {ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_INICIAL , idFormacion};
	}

	if (rango_menor.size() != 0){
		mapeador->mapearFechaLeida(rango_menor, &anio, &mes, &dia, &rangoHoras);
		u_int32_t idRango = mapeador->convertirRango(anio, mes, dia, rangoHoras);
		max = {~ID_CLAVE_VACIA,idRango,~ID_CLAVE_VACIA, ~ID_CLAVE_VACIA, idFormacion};
	}
	else{
		max = {~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA, ~ID_CLAVE_VACIA, idFormacion};
	}

	ParametroQuery parametroQuery (&min, &max);

	ArbolUB<DIMENSION_CLAVES, CANTIDAD_BITS_CLAVES> arbol(PATH_INDICE, TAMANIO_NODO);

	(QueryEjecutor::getInstance())->execute(arbol, &parametroQuery, archSalida,QUERY_ACCIDENTES_FORMACION);
}

void consultaFallasFormacion(std::string& formacion, std::string& rango_menor, std::string& rango_mayor){
	unsigned int anio;
	unsigned char mes, dia;
	std::string rangoHoras;
	Point<DIMENSION_CLAVES> min, max;
	std::string dirInput = getenv("OUTPUT");
	std::string archSalida = dirInput.append("/").append(PATH_QUERY_FALLAS_FORMACION);

	u_int32_t idFormacion = (u_int32_t) (atoi(formacion.c_str())) ;
	Mapeador* mapeador = Mapeador::getInstance();
	if (rango_mayor.size() != 0){
		mapeador->mapearFechaLeida(rango_mayor, &anio, &mes, &dia, &rangoHoras);
		u_int32_t idRango = mapeador->convertirRango(anio, mes, dia, rangoHoras);
		min = {ID_CLAVE_VACIA,idRango,ID_CLAVE_INICIAL, ID_CLAVE_VACIA, idFormacion};
	}
	else{
		min = {ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_INICIAL, ID_CLAVE_VACIA, idFormacion};
	}

	if (rango_menor.size() != 0){
		mapeador->mapearFechaLeida(rango_menor, &anio, &mes, &dia, &rangoHoras);
		u_int32_t idRango = mapeador->convertirRango(anio, mes, dia, rangoHoras);
		max = {~ID_CLAVE_VACIA,idRango,~ID_CLAVE_VACIA, ~ID_CLAVE_VACIA, idFormacion};
	}
	else{
		max = {~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA, ~ID_CLAVE_VACIA, idFormacion};
	}

	ParametroQuery parametroQuery (&min, &max);

	ArbolUB<DIMENSION_CLAVES, CANTIDAD_BITS_CLAVES> arbol(PATH_INDICE, TAMANIO_NODO);

	(QueryEjecutor::getInstance())->execute(arbol, &parametroQuery, archSalida,QUERY_FALLAS_FORMACION);
}

void consultaTrenesAccidente(std::string& accidente, std::string& rango_menor, std::string& rango_mayor){
	unsigned int anio;
	unsigned char mes, dia;
	std::string rangoHoras;
	Point<DIMENSION_CLAVES> min, max;
	std::string dirInput = getenv("OUTPUT");
	std::string archSalida = dirInput.append("/").append(PATH_QUERY_TRENES_ACCIDENTE);
	Mapeador* mapeador = Mapeador::getInstance();

	u_int32_t idAccidente = mapeador->mapStringToId(accidente);
	if (rango_mayor.size() != 0){
		mapeador->mapearFechaLeida(rango_mayor, &anio, &mes, &dia, &rangoHoras);
		u_int32_t idRango = mapeador->convertirRango(anio, mes, dia, rangoHoras);
		min = {ID_CLAVE_VACIA,idRango,ID_CLAVE_VACIA, idAccidente, ID_CLAVE_INICIAL};
	} else {
		min = {ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_VACIA, idAccidente, ID_CLAVE_INICIAL};
	}

	if (rango_menor.size() != 0){
		mapeador->mapearFechaLeida(rango_menor, &anio, &mes, &dia, &rangoHoras);
		u_int32_t idRango = mapeador->convertirRango(anio, mes, dia, rangoHoras);
		max = {~ID_CLAVE_VACIA,idRango,~ID_CLAVE_VACIA, idAccidente, ~ID_CLAVE_VACIA};
	}
	else{
		max = {~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA, idAccidente, ~ID_CLAVE_VACIA};
	}

	ParametroQuery parametroQuery (&min, &max);

	ArbolUB<DIMENSION_CLAVES, CANTIDAD_BITS_CLAVES> arbol(PATH_INDICE, TAMANIO_NODO);

	(QueryEjecutor::getInstance())->execute(arbol, &parametroQuery, archSalida,QUERY_TRENES_ACCIDENTE);
}

void consultaTrenesFalla(std::string& falla, std::string& rango_menor, std::string& rango_mayor){
	unsigned int anio;
	unsigned char mes, dia;
	std::string rangoHoras;
	Point<DIMENSION_CLAVES> min, max;
	std::string dirInput = getenv("OUTPUT");
	std::string archSalida = dirInput.append("/").append(PATH_QUERY_TRENES_FALLA);
	Mapeador* mapeador = Mapeador::getInstance();

	u_int32_t idFalla = mapeador->mapStringToId(falla);
	if (rango_mayor.size() != 0){
		mapeador->mapearFechaLeida(rango_mayor, &anio, &mes, &dia, &rangoHoras);
		u_int32_t idRango = mapeador->convertirRango(anio, mes, dia, rangoHoras);
		min = {ID_CLAVE_VACIA,idRango,idFalla, ID_CLAVE_VACIA, ID_CLAVE_INICIAL};
	}
	else{
		min = {ID_CLAVE_VACIA,ID_CLAVE_VACIA,idFalla, ID_CLAVE_VACIA, ID_CLAVE_INICIAL};
	}

	if (rango_menor.size() != 0){
		mapeador->mapearFechaLeida(rango_menor, &anio, &mes, &dia, &rangoHoras);
		u_int32_t idRango = mapeador->convertirRango(anio, mes, dia, rangoHoras);
		max = {~ID_CLAVE_VACIA,idRango,idFalla, ~ID_CLAVE_VACIA,  ~ID_CLAVE_VACIA};
	}
	else{
		max = {~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,idFalla, ~ID_CLAVE_VACIA, ~ID_CLAVE_VACIA};
	}

	ParametroQuery parametroQuery (&min, &max);

	ArbolUB<DIMENSION_CLAVES, CANTIDAD_BITS_CLAVES> arbol(PATH_INDICE, TAMANIO_NODO);

	(QueryEjecutor::getInstance())->execute(arbol, &parametroQuery, archSalida,QUERY_TRENES_FALLA);
}

void consultaTodasLasFallas(){

	std::string dirInput = getenv("OUTPUT");
	std::string archFallas = dirInput.append("/").append(PATH_QUERY_TODAS_LAS_FALLAS);

    Point<DIMENSION_CLAVES> min = {ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_INICIAL,ID_CLAVE_VACIA,ID_CLAVE_VACIA}; // no quiero fallas que no esten cargadas
    Point<DIMENSION_CLAVES> max = {~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA};

	ParametroQuery parametroQuery (&min, &max);

	ArbolUB<DIMENSION_CLAVES, CANTIDAD_BITS_CLAVES> arbol(PATH_INDICE, TAMANIO_NODO);

	(QueryEjecutor::getInstance())->execute(arbol, &parametroQuery, archFallas,QUERY_TODAS_LAS_FALLAS);
}

void consultaTodosLosAccidentes(){
	std::string dirInput = getenv("OUTPUT");
	std::string archFallas = dirInput.append("/").append(PATH_QUERY_TODOS_LOS_ACCIDENTES);

    Point<DIMENSION_CLAVES> min = {ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_INICIAL,ID_CLAVE_VACIA};
    Point<DIMENSION_CLAVES> max = {~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA};

	ParametroQuery parametroQuery (&min, &max);

	ArbolUB<DIMENSION_CLAVES, CANTIDAD_BITS_CLAVES> arbol(PATH_INDICE, TAMANIO_NODO);

	(QueryEjecutor::getInstance())->execute(arbol, &parametroQuery, archFallas,QUERY_TODOS_LOS_ACCIDENTES);
}

void consultaTodosLasLineas(){
	std::string dirInput = getenv("OUTPUT");
	std::string archFallas = dirInput.append("/").append(PATH_QUERY_TODAS_LAS_LINEAS);

    Point<DIMENSION_CLAVES> min = {ID_CLAVE_INICIAL,ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_VACIA};
    Point<DIMENSION_CLAVES> max = {~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA};

	ParametroQuery parametroQuery (&min, &max);

	ArbolUB<DIMENSION_CLAVES, CANTIDAD_BITS_CLAVES> arbol(PATH_INDICE, TAMANIO_NODO);

	(QueryEjecutor::getInstance())->execute(arbol, &parametroQuery, archFallas,QUERY_TODAS_LAS_LINEAS);
}

void consultaTodosLasFormaciones(){
	std::string dirInput = getenv("OUTPUT");
	std::string archFallas = dirInput.append("/").append(PATH_QUERY_TODAS_LAS_FORMACIONES);

    Point<DIMENSION_CLAVES> min = {ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_VACIA,ID_CLAVE_INICIAL};
    Point<DIMENSION_CLAVES> max = {~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA,~ID_CLAVE_VACIA};

	ParametroQuery parametroQuery (&min, &max);

	ArbolUB<DIMENSION_CLAVES, CANTIDAD_BITS_CLAVES> arbol(PATH_INDICE, TAMANIO_NODO);

	(QueryEjecutor::getInstance())->execute(arbol, &parametroQuery, archFallas,QUERY_TODAS_LAS_FORMACIONES);
}

void altaClave (char** argv){

	ArbolUB<DIMENSION_CLAVES, CANTIDAD_BITS_CLAVES> arbol(PATH_INDICE, TAMANIO_NODO);
	Mapeador* mapeador = Mapeador::getInstance();
	int i = 0;
	unsigned int anio = 0;
	unsigned char mes = 0;
	unsigned char dia = 0;
	std::string rango;
	std::string clave;

	Point<DIMENSION_CLAVES> point;

	// linea

	if  (argv[i+1]){
		clave = argv[i+1];
		point[i] = mapeador->mapStringToId(clave);
	}
	else
		point[i] = ID_CLAVE_VACIA;
	++i;

	// rango fecha
	if  (argv[i+1]){
		clave = argv[i+1];
		mapeador->mapearFechaLeida(clave, &anio, &mes, &dia, &rango);
		point[i] = mapeador->convertirRango(anio, mes, dia, rango);
	}
	else
		point[i] = ID_CLAVE_VACIA;
	++i;

	// falla
	if  (argv[i+1]){
		clave = argv[i+1];
		point[i] = mapeador->mapStringToId(clave);
	}
	else
		point[i] = ID_CLAVE_VACIA;
	++i;

	// accidente
	if  (argv[i+1]){
		clave = argv[i+1];
		point[i] = mapeador->mapStringToId(clave);
	}
	else
		point[i] = ID_CLAVE_VACIA;
	++i;

	// formacion
	point[i] = (u_int32_t)atoi(argv[i+1]);

    RegistroUB<DIMENSION_CLAVES, CANTIDAD_BITS_CLAVES> reg (point);
    arbol.insertar(reg);
}

bool validarFormatoFechayHora(char *cFecha, std::string* sRangoHorarioyFecha){
	std::string sFecha(cFecha);

	if (sFecha.length() != 12)
		return false;

	for(unsigned int i=0; i < sFecha.length(); i++){
		if((char)sFecha[i] < '0' || (char)sFecha[i] > '9')
			return false;
	}

	int iHora, iMins, iDia, iMes;
	std::string sHora, sDia, sMes, sAnio;

	sHora = sFecha.substr(0,2);
	sDia = sFecha.substr(4,2);
	sMes = sFecha.substr(6,2);
	sAnio = sFecha.substr(8,4);

	iHora = atoi(sHora.c_str());
	iMins = atoi(sFecha.substr(2,2).c_str());
	iDia  = atoi(sDia.c_str());
	iMes = atoi(sMes.c_str());

	if(iHora > 24 || iHora < 0)
		return false;

	if(iMins > 60 || iMins < 0)
		return false;

	if(iMes > 12 || iMes < 1)
		return false;

	switch (iMes) {
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			if(iDia > 31 || iDia < 1)
				return false;
			break;
		case 2:
			if(iDia > 28 || iDia < 1)
				return false;
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			if(iDia > 30 || iDia < 1)
				return false;
			break;
	}


	char cResultado[50];

	if(iMins < 30)
		snprintf(cResultado, sizeof(cResultado),"%s:00 - %s:30 %s/%s/%s",sHora.c_str(), sHora.c_str(), sDia.c_str(), sMes.c_str(), sAnio.c_str());
	else{
		if(iHora == 23)
			iHora = 0;
		else
			iHora++;
		snprintf(cResultado, sizeof(cResultado),"%s:30 - %02d:00 %s/%s/%s",sHora.c_str(), iHora, sDia.c_str(), sMes.c_str(), sAnio.c_str());
	}

	*sRangoHorarioyFecha = std::string(cResultado);

	return true;
}

int main(int argc, char** argv) {

	if(!controlParametros(argc, argv))
		return false;

	if(alta){
		altaClave(++argv);
	}

	if(carga_inicial){

		if(fileExists(PATH_INDICE)){
			remove(PATH_INDICE);
		}

		ArbolUB<DIMENSION_CLAVES, CANTIDAD_BITS_CLAVES> arbol(PATH_INDICE, TAMANIO_NODO);
		std::string archivo_claves = std::string(argCargaInicial);
		CargadorMasivo* cargadorMasivo = CargadorMasivo::getInstance();
	    cargadorMasivo->cargarClaves(arbol, archivo_claves);
	} else {
		if(!fileExists(PATH_INDICE)){
			std::cout << "Debe realizarse la carga inicial antes de proceder con las consultas" << std::endl;
			return false;
		}
	}

	if(filtra_falla && !filtra_formaciones)
		consultaTodasLasFallas();

	if(filtra_accidentes && !filtra_formaciones)
		consultaTodosLosAccidentes();

	if(filtra_lineas)
		consultaTodosLasLineas();

	if(filtra_formaciones && !filtra_falla && !filtra_accidentes)
		consultaTodosLasFormaciones();

	std::string paramConsulta, paramRangos;

	/*
	 * Como har�amos para filtrar por una fecha menor y otra mayor?
	 * Para ir probando en estos ejemplos utilic� la fecha menor como rango enviado
	 * para realizar la consulta. Quedar�a ver como ser�a si la consulta quiere obtener
	 * resultados entre ciertas fechas
	 *
	 */

	if(filtra_formaciones && filtra_falla && argFormacion){
		paramConsulta = std::string(argFormacion);
		consultaFallasFormacion(paramConsulta, rangoHorarioyFechaMenor, rangoHorarioyFechaMayor);
	}

	if(filtra_formaciones && filtra_accidentes && argFormacion){
		paramConsulta = std::string(argFormacion);
		consultaAccidentesFormacion(paramConsulta, rangoHorarioyFechaMenor, rangoHorarioyFechaMayor);
	}

	if(filtra_formaciones && filtra_accidentes && argAccidente){
		paramConsulta = std::string(argAccidente);
		consultaTrenesAccidente(paramConsulta, rangoHorarioyFechaMenor, rangoHorarioyFechaMayor);
	}

	if(filtra_formaciones && filtra_falla && argFalla){
		paramConsulta = std::string(argFalla);
		consultaTrenesFalla(paramConsulta, rangoHorarioyFechaMenor, rangoHorarioyFechaMayor);
	}

    return 0;
}

bool controlParametros(int argc, char** argv){
	int long_val;
	int long_opt_index = 0;
	char ch;

	option longOptions[] = {
			{"alta", 0, &long_val, 'i'},
			{"formaciones", 2, &long_val, 'f'},
			{"fallas", 2, &long_val, 'b'},
			{"accidentes", 2, &long_val, 'a'},
			{"lineas", 0, &long_val, 'l'},
			{"fecha_menor_a", 1, &long_val, 'y'},
			{"fecha_mayor_a", 1, &long_val, 'z'},
			{"carga_inicial", 1, &long_val, 'c'},
						{0,0,0,0}};

	std::string error = "Consulta ambigua. Las opciones validas son:\n";
	error += "          --alta\n";
	error += "                Se realiza alta de una clave\n\n";
	error += "          --accidentes\n";
	error += "                Lista todos los accidentes\n\n";
	error += "          --lineas\n";
	error += "                Lista todas las lineas\n\n";
	error += "          --formaciones\n";
	error += "                Lista todas las formaciones\n\n";
	error += "          --fallas\n";
	error += "                Lista todas las fallas\n\n";
	error += "          --accidentes --formaciones=<valor> [--fecha_menor_a hhmmddMMyyyy y/o --fecha_mayor_a hhmmddMMyyyy]\n";
	error += "                Lista todos los accidentes de una cierta formacion\n\n";
	error += "          --fallas --formaciones=<valor> [--fecha_menor_a hhmmddMMyyyy y/o --fecha_mayor_a hhmmddMMyyyy]\n";
	error += "                Lista todas las fallas de una cierta formacion\n\n";
	error += "          --formacion --accidente=<valor> [--fecha_menor_a hhmmddMMyyyy y/o --fecha_mayor_a hhmmddMMyyyy]\n";
	error += "                Lista todas las formaciones que tienen cierto accidente\n\n";
	error += "          --formacion --fallas=<valor> [--fecha_menor_a hhmmddMMyyyy y/o --fecha_mayor_a hhmmddMMyyyy]\n";
	error += "                Lista todas las formaciones que tienen cierta falla\n\n";

	while((ch = getopt_long(argc, argv, "hl", longOptions, &long_opt_index)) != -1) {
		switch(ch){
		case 'h':
			std::cout << "Usage: ";
			std::cout << "      " << argv[0] << " [options]" << std::endl;
			std::cout << " " << std::endl;
			std::cout << "Options: " << std::endl;
			std::cout << "        " << "-h " << std::endl;
			std::cout << "                 Menu de ayuda"<< std::endl;
			std::cout << " " << std::endl;
			std::cout << "        " << "--alta " << std::endl;
			std::cout << "                 Se realiza alta de una clave"<< std::endl;
			std::cout << " " << std::endl;
			std::cout << "        " << "--carga_inicial " << std::endl;
			std::cout << "                 Realiza la primera carga obligatoria"<< std::endl;
			std::cout << " " << std::endl;
			std::cout << "        " << "--alta " << std::endl;
			std::cout << "                 Se realiza alta de una clave"<< std::endl;
			std::cout << " " << std::endl;
			std::cout << "        " << "--accidentes " << std::endl;
			std::cout << "                 Lista todos los accidentes"<< std::endl;
			std::cout << " " << std::endl;
			std::cout << "        " << "--fallas " << std::endl;
			std::cout << "                 Lista todas las fallas"<< std::endl;
			std::cout << " " << std::endl;
			std::cout << "        " << "--formaciones " << std::endl;
			std::cout << "                 Lista todas las formaciones"<< std::endl;
			std::cout << " " << std::endl;
			std::cout << "        " << "--lineas " << std::endl;
			std::cout << "                 Lista todas las lineas"<< std::endl;
			std::cout << " " << std::endl;
			std::cout << "        " << "--formaciones --fallas=<valor> [--fecha_menor_a hhmmddMMyyyy y/o --fecha_mayor_a hhmmddMMyyyy]"<< std::endl;
			std::cout << "                 Recupera todos las formaciones que tienen cierta falla"<< std::endl;
			std::cout << " " << std::endl;
			std::cout << "        " << "--formaciones --accidentes=<valor> [--fecha_menor_a hhmmddMMyyyy y/o --fecha_mayor_a hhmmddMMyyyy]"<< std::endl;
			std::cout << "                 Recupera todos las formaciones que tienen cierto accidente"<< std::endl;
			std::cout << " " << std::endl;
			std::cout << "        " << "--fallas --formaciones=<valor> [--fecha_menor_a hhmmddMMyyyy y/o --fecha_mayor_a hhmmddMMyyyy]"<< std::endl;
			std::cout << "                 Recupera todas las fallas de una cierta formacion"<< std::endl;
			std::cout << " " << std::endl;
			std::cout << "        " << "--accidentes --formaciones=<valor> [--fecha_menor_a hhmmddMMyyyy y/o --fecha_mayor_a hhmmddMMyyyy]"<< std::endl;
			std::cout << "                 Recupera todas las acciones de una cierta formacion"<< std::endl;

			exit(0);
			break;
		case 0:
			switch(long_val){
			case 'i':
				alta = true;
				return true;
				break;
			case 'f':
				if(optarg){
					argFormacion = optarg;
				}
				/*
				 * Se recibe --accidentes --formaciones
				 * se esperaba --accidentes --formaciones=<consulta>
				 */
				if(filtra_accidentes && !argFormacion && !argAccidente){
					std::cout << error;
					return false;
				}
				/*
				 * Se recibe --accidentes=<consulta1> --formaciones=<consulta2>
				 * se esperaba --accidentes --formaciones=<consulta>
				 */
				if(filtra_accidentes && argFormacion && argAccidente){
					std::cout << error;
					return false;
				}

				/*
				 * Se recibe --fallas --formaciones
				 * se esperaba --fallas --formaciones=<consulta>
				 */
				if(filtra_falla && !argFalla && !argFormacion){
					std::cout << error;
					return false;
				}
				/*
				 * Se recibe --fallas=<consulta1> --formaciones=<consulta2>
				 * se esperaba --fallas --formaciones=<consulta>
				 */
				if(filtra_falla && argFormacion && argFalla){
					std::cout << error;
					return false;
				}

				if(filtra_lineas || carga_inicial){
					std::cout << error;
					return false;
				}

				filtra_formaciones = true;
				break;

			case 'b':
				if(optarg)
					argFalla = optarg;
				/*
				 * Se recibe --formaciones=<consulta> --falla=<consulta>
				 * se esperaba --formaciones --falla=<consulta>
				 */
				if(filtra_formaciones && argFormacion && argFalla){
					std::cout << error;
					return false;
				}
				/*
				 * Se recibe --formaciones --accidentes=<consulta>
				 * que corresponde a otra consulta
				 */
				if(filtra_accidentes && filtra_formaciones && argAccidente){
					std::cout << error;
					return false;
				}
				if(filtra_accidentes || filtra_lineas || carga_inicial){
					std::cout << error;
					return false;
				}
				filtra_falla = true;
				break;
			case 'a':
				if(optarg)
					argAccidente = optarg;
				/*
				 * Se recibe --formaciones=<consulta> --accidentes=<consulta>
				 * se esperaba --formaciones --accidentes=<consulta>
				 */
				if(filtra_formaciones && argFormacion && argAccidente){
					std::cout << error;
					return false;
				}
				/*
				 * Se recibe --formaciones --fallas=<consulta>
				 * que corresponde a otra consulta
				 */
				if(filtra_formaciones && filtra_falla){
					std::cout << error;
					return false;
				}
				if(filtra_falla || filtra_lineas || carga_inicial){
					std::cout << error;
					return false;
				}
				filtra_accidentes = true;
				break;
			case 'l':
				if(filtra_falla || filtra_accidentes || carga_inicial ||
						filtra_formaciones || filtra_fecha_mayor_a || filtra_fecha_menor_a){
					std::cout << error;
					return false;
				}

				filtra_lineas = true;
				break;
			case 'c':
				if(filtra_falla || filtra_accidentes ||
						filtra_formaciones || filtra_fecha_mayor_a || filtra_fecha_menor_a){
					std::cout << error;
					return false;
				}

				argCargaInicial = optarg;
				carga_inicial = true;
				break;
			case 'y':
				argFechaMenor = optarg;
				if((argFormacion && !filtra_falla && !filtra_accidentes) ||
						((argAccidente || argFalla) && !filtra_formaciones)){
					std::cout << error;
					return false;
				}
				if (!validarFormatoFechayHora(argFechaMenor, &rangoHorarioyFechaMenor)){
					std::cout << "La fecha ingresa no es valida. El formato aceptado es hhmmddMMyyyy." << std::endl;
					return false;
				}
				filtra_fecha_menor_a = true;
				break;
			case 'z':
				argFechaMayor = optarg;
				if((argFormacion && !filtra_falla && !filtra_accidentes) ||
						((argAccidente || argFalla) && !filtra_formaciones)){
					std::cout << error;
					return false;
				}

				if (!validarFormatoFechayHora(argFechaMayor,&rangoHorarioyFechaMayor)){
					std::cout << "La fecha ingresa no es valida. El formato aceptado es hhmmddMMyyyy." << std::endl;
					return false;
				}

				filtra_fecha_mayor_a = true;
				break;
			case 0:
				std::cout << "La opcion : " << argv[optind] << std::endl;
				break;
			}
			break;
		}
	}

	return true;
}
